package com.example.shiro.common.config.shiro;

import com.example.shiro.common.util.JWTToken;
import com.example.shiro.common.util.JwtUtil;
import com.example.shiro.model.sys.entity.dto.UserInfoDto;
import com.example.shiro.model.sys.service.UserService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Objects;

/**
 * @auther 严旭平
 * @date 2020/4/1616:31
 * @Description
 */
public class MyShiroRealm extends AuthorizingRealm {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private UserService userService;

    /**
     * 必须重写此方法，不然坑死你
     * @param token
     * @return
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JWTToken;
    }

    /**
     * 处理授权 只有在拦截器中配置权限信息或者采用注解形式配置拦截 信息时候才会采用此处的验证方法
     * @param principal
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principal ) {
        logger.debug("进入到授权方法doGetAuthorizationInfo中");
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        UserInfoDto user = userService.getUserInfoByUsername( JwtUtil.getUsername( principal.toString())  );
        /**
         * 设置用户权限和角色
         */
        authorizationInfo.setRoles( user.getRoleNameList() );
        authorizationInfo.setStringPermissions( user.getAuthNameList() );

        return authorizationInfo;

    }

    /**
     * 处理认证
     * @param auth
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth ) throws AuthenticationException {
       logger.debug("进入到MyShiroRealm中的身份认证当中");
       logger.debug("auth信息为" + auth );
        /**
         * 1.获取token凭证信息
         */
        String token = (String)auth.getCredentials();

        /**
         * 验证token
         */
        String username = JwtUtil.getUsername( token );
        if( username == null ){
            logger.info("token异常");
            throw  new AuthenticationException("token异常");
        }
        /**
         * 验证token有效性
         */
        if( !JwtUtil.isTokenExpired( token ) ){
            throw new AuthenticationException("token已失效");
        }
        /**
         * 验证密码
         */
        UserInfoDto user = userService.getUserInfoByUsername( username );
        if ( Objects.isNull( user ) ) {
            logger.info("用户名不存在");
            throw new AuthenticationException("用户名存在");
        }

        /**
         * 校验用户状态
         */
        if( !user.getStatus() ){
            throw new AuthenticationException("此用户已被禁用，请联系管理员开启");
        }

        return new SimpleAuthenticationInfo( token , token , user.getUsername() );
    }
}
